package cn.anecansaitin.whimsy.common.entity;

import cn.anecansaitin.whimsy.common.capabilities.battle.DoomfistBattle;
import cn.anecansaitin.whimsy.common.capabilities.battle.IBattleMode;
import cn.anecansaitin.whimsy.common.register.ModDamageSources;
import cn.anecansaitin.whimsy.common.register.ModEntities;
import it.unimi.dsi.fastutil.floats.FloatConsumer;
import net.minecraft.util.Mth;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.projectile.Projectile;
import net.minecraft.world.entity.projectile.ProjectileUtil;
import net.minecraft.world.level.ClipContext;
import net.minecraft.world.level.Level;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.EntityHitResult;
import net.minecraft.world.phys.HitResult;
import net.minecraft.world.phys.Vec3;

import javax.annotation.Nullable;

public class LightBullet extends Projectile {
    @Nullable
    private FloatConsumer ultimateCharger;

    public LightBullet(EntityType<LightBullet> entityType, Level level) {
        super(entityType, level);
    }

    public LightBullet(Entity shooter, @Nullable FloatConsumer ultimateCharger) {
        super(ModEntities.LIGHT_BULLET.get(), shooter.level());
        setOwner(shooter);
        setPos(shooter.getEyePosition().add(0, -0.1, 0));
        this.ultimateCharger = ultimateCharger;
    }

    @Override
    protected void defineSynchedData() {

    }

    @Override
    public void tick() {
        Entity entity = this.getOwner();
        if (this.level().isClientSide || (entity == null || !entity.isRemoved()) && this.level().hasChunkAt(this.blockPosition())) {
            super.tick();
            HitResult hitresult = ProjectileUtil.getHitResultOnMoveVector(this, this::canHitEntity, ClipContext.Block.COLLIDER);
            if (hitresult.getType() != HitResult.Type.MISS && !net.neoforged.neoforge.event.EventHooks.onProjectileImpact(this, hitresult)) {
                this.onHit(hitresult);
            }

            this.checkInsideBlocks();
            Vec3 vec3 = this.getDeltaMovement();
            double d0 = this.getX() + vec3.x;
            double d1 = this.getY() + vec3.y;
            double d2 = this.getZ() + vec3.z;
            this.setPos(d0, d1, d2);
        } else {
            this.discard();
        }
    }

    @Override
    protected void onHitEntity(EntityHitResult result) {
        float damageAmount = 1.5f;
        Entity target = result.getEntity();
        DamageSource damageSource;
        Entity owner = getOwner();
        damageSource = ModDamageSources.owNoKnockback(owner == null ? level() : owner.level(), owner, this, position());
        target.hurt(damageSource, damageAmount);
        chargeUltimate(damageAmount);
        discard();
    }

    @Override
    protected void onHitBlock(BlockHitResult pResult) {
        super.onHitBlock(pResult);
        discard();
    }

    @Override
    public void shootFromRotation(Entity pShooter, float pX, float pY, float pZ, float pVelocity, float pInaccuracy) {
        float f = -Mth.sin(pY * (float) (Math.PI / 180.0)) * Mth.cos(pX * (float) (Math.PI / 180.0));
        float f1 = -Mth.sin((pX + pZ) * (float) (Math.PI / 180.0));
        float f2 = Mth.cos(pY * (float) (Math.PI / 180.0)) * Mth.cos(pX * (float) (Math.PI / 180.0));
        this.shoot(f, f1, f2, pVelocity, pInaccuracy);
    }

    private void chargeUltimate(float damage) {
        if (ultimateCharger == null) {
            Entity owner = getOwner();

            if (owner == null) {
                return;
            }

            IBattleMode battleMode = owner.getCapability(IBattleMode.BATTLE_MODE);

            if (battleMode == null) {
                return;
            }

            if (!(battleMode.getController() instanceof DoomfistBattle doomfist)) {
                return;
            }

            this.ultimateCharger = doomfist.ultimateCharger;
        } else {
            ultimateCharger.accept(damage);
        }
    }
}